package com.cloud.example.business.flow.controller.parallel;


import com.cloud.async.flow.web.client.FlowTemplate;
import com.cloud.async.flow.wrapper.WorkerWrapper;
import com.cloud.example.business.flow.controller.parallel.worker.ParWorker1;
import com.cloud.example.business.flow.controller.parallel.worker.ParWorker2;
import com.cloud.example.business.flow.controller.parallel.worker.ParWorker3;
import com.cloud.example.business.flow.controller.parallel.worker.ParWorker4;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;

/**
 *
 *
 * @author chengr
 */
@RequestMapping("/api/flow")
@RestController
public class ParallelController {

    /**
     * logger
     */
    private final Log logger = LogFactory.getLog(getClass());

    @Autowired
    FlowTemplate flowTemplate;

    /**
     * 3个任务并行
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @GetMapping("/parallel")
    public String parallel() {

        ParWorker1 w1 = new ParWorker1();
        ParWorker2 w2 = new ParWorker2();
        ParWorker3 w3 = new ParWorker3();

        WorkerWrapper<String, String> workerWrapper2 = new WorkerWrapper.Builder<String, String>()
                .worker(w2)
                .callback(w2)
                .param("2")
                .build();

        WorkerWrapper<String, String> workerWrapper1 = new WorkerWrapper.Builder<String, String>()
                .worker(w1)
                .callback(w1)
                .param("1")
                .build();

        WorkerWrapper<String, String> workerWrapper3 = new WorkerWrapper.Builder<String, String>()
                .worker(w3)
                .callback(w3)
                .param("0")
                .build();

        try {
            flowTemplate.startWork(3000, workerWrapper3, workerWrapper2, workerWrapper1);
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "success!";
    }


    /**
     * 1个执行完毕后，开启另外两个，另外两个执行完毕后，开始第4个
     * @return
     */
    @GetMapping("/parallelDepend")
    public String parallelDepend() {
        ParWorker4 w = new ParWorker4();
        ParWorker1 w1 = new ParWorker1();
        ParWorker2 w2 = new ParWorker2();
        ParWorker3 w3 = new ParWorker3();
        WorkerWrapper<String, String> workerWrapper3 =  new WorkerWrapper.Builder<String, String>()
                .worker(w3)
                .callback(w3)
                .param("3")
                .build();
        WorkerWrapper<String, String> workerWrapper2 =  new WorkerWrapper.Builder<String, String>()
                .worker(w2)
                .callback(w2)
                .param("2")
                .next(workerWrapper3)
                .build();
        WorkerWrapper<String, String> workerWrapper1 =  new WorkerWrapper.Builder<String, String>()
                .worker(w1)
                .callback(w1)
                .param("1")
                .next(workerWrapper3)
                .build();
        WorkerWrapper<String, String> workerWrapper =  new WorkerWrapper.Builder<String, String>()
                .worker(w)
                .callback(w)
                .param("0")
                .next(workerWrapper1, workerWrapper2)
                .build();
        try {
            flowTemplate.startWork(3000, workerWrapper);
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success!";
    }

    /**
     * 另一种写法：com.cloud.example.business.flow.controller.parallel.ParallelController#parallelDepend()
     */
    void parallelDependOther() {
        ParWorker4 w = new ParWorker4();
        ParWorker1 w1 = new ParWorker1();
        ParWorker2 w2 = new ParWorker2();
        ParWorker3 w3 = new ParWorker3();
        WorkerWrapper<String, String> workerWrapper =  new WorkerWrapper.Builder<String, String>()
                .worker(w)
                .callback(w)
                .param("0")
                .build();

        WorkerWrapper<String, String> workerWrapper3 =  new WorkerWrapper.Builder<String, String>()
                .worker(w3)
                .callback(w3)
                .param("3")
                .build();

        WorkerWrapper<String, String> workerWrapper2 =  new WorkerWrapper.Builder<String, String>()
                .worker(w2)
                .callback(w2)
                .param("2")
                .depend(workerWrapper)
                .next(workerWrapper3)
                .build();

        WorkerWrapper<String, String> workerWrapper1 =  new WorkerWrapper.Builder<String, String>()
                .worker(w1)
                .callback(w1)
                .param("1")
                .depend(workerWrapper)
                .next(workerWrapper3)
                .build();
    }


}
